package com.codebo.homiematchbackend.websocket;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.codebo.homiematchbackend.common.ErrorCode;
import com.codebo.homiematchbackend.exception.ThrowUtils;
import com.codebo.homiematchbackend.model.dto.chat.ChatRequest;
import com.codebo.homiematchbackend.model.entity.Chat;
import com.codebo.homiematchbackend.model.entity.TeamUser;
import com.codebo.homiematchbackend.model.vo.ChatVO;
import com.codebo.homiematchbackend.service.ChatService;
import com.codebo.homiematchbackend.service.TeamUserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import jakarta.annotation.Resource;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Slf4j
@Component
public class ChatWebSocketHandler extends TextWebSocketHandler
{

    @Resource
    private TeamUserService teamUserService;

    @Resource
    private ChatService chatService;

    private static final Map<Long, WebSocketSession> onlineUsers = new ConcurrentHashMap<>();
    private static final ObjectMapper mapper = new ObjectMapper();

    /* 连接建立：把 userId 解析出来并缓存 */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception
    {
        Long userId = parseUserId(session);
        if (userId != null)
        {
            onlineUsers.put(userId, session);
            log.info("用户上线: {}", userId);
        }
    }

    /* 收到消息 */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception
    {
        ChatRequest chatRequest = mapper.readValue(message.getPayload(), ChatRequest.class);
        Long fromId = chatRequest.getFromId();
        Long toId = chatRequest.getToId();
        Long teamId = chatRequest.getTeamId();
        String text = chatRequest.getText();
        Integer chatType = chatRequest.getChatType();
        System.out.println("chatRequest = " + chatRequest);

//        ThrowUtils.throwIf(fromId.equals(toId), ErrorCode.PARAMS_ERROR, "不能聊天自己");
        if(fromId.equals(toId))
        {
            //存入数据库
            Chat chat = new Chat();
            chat.setFromId(fromId);
            chat.setToId(toId);
            chat.setText(text);
            chat.setChatType(1);
            chatService.save(chat);
            return;
        }

        if (Integer.valueOf(1).equals(chatType))
        {

            //存入数据库
            Chat chat = new Chat();
            chat.setFromId(fromId);
            chat.setToId(toId);
            chat.setText(text);
            chat.setChatType(1);
            chat.setCreateTime(new Date());
            chatService.save(chat);

            sendToUser(chat);
        } else if (Integer.valueOf(2).equals(chatType))
        {

            //存入数据库
            Chat chat = new Chat();
            chat.setFromId(fromId);
            chat.setToId(toId);
            chat.setText(text);
            chat.setChatType(2);
            chat.setTeamId(teamId);
            chat.setCreateTime(new Date());
            chatService.save(chat);

            sendToGroup(chat);
        }
    }

    /* 连接关闭 */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception
    {
        Long userId = parseUserId(session);
        if (userId != null)
        {
            onlineUsers.remove(userId);
            log.info("用户下线: {}", userId);
        }
    }

    /* =============== 私有工具 =============== */

    private void sendToUser(Chat chat) throws IOException
    {
        ChatVO chatVO = new ChatVO();
        BeanUtil.copyProperties(chat, chatVO);
        Long toId = chatVO.getToId();

        String chatVOJson = mapper.writeValueAsString(chatVO);

        WebSocketSession s = onlineUsers.get(toId);
        if (s != null && s.isOpen())
        {
            s.sendMessage(new TextMessage(chatVOJson));
            System.out.println(chat.getFromId() + "发送消息给用户 " + toId + ":" + chat.getText());
        }
    }

    private void sendToGroup(Chat chat) throws IOException
    {
        Long fromId = chat.getFromId();
        Long teamId = chat.getTeamId();

        List<Long> memberIds = getGroupMembers(teamId);
        Chat chatMember = new Chat();
        for (Long userId : memberIds)
        {
            if (userId.equals(fromId))
            {
                continue;
            }
            chatMember.setFromId(fromId);
            chatMember.setToId(userId);
            chatMember.setTeamId(teamId);
            chatMember.setText(chat.getText());
            chatMember.setChatType(2);

            sendToUser(chatMember);
        }
    }

    private List<Long> getGroupMembers(Long teamId)
    {
        QueryWrapper<TeamUser> qw = new QueryWrapper<>();
        qw.eq("team_id", teamId);
        List<TeamUser> list = teamUserService.list(qw);
        return list.stream().map(TeamUser::getUserId).collect(Collectors.toList());
    }

    /* 从 uri 里解析 /chat/{userId} */
    private Long parseUserId(WebSocketSession session)
    {
        String uri = session.getUri().toString();          // /chat/123
        String[] seg = uri.split("/");
        try
        {
            return Long.valueOf(seg[seg.length - 1]);
        } catch (NumberFormatException e)
        {
            return null;
        }
    }
}
